
#include <os/find.h>

#include <cassert>
#include <stdexcept>

namespace os
{
    path FindPrev(const path& dir,const path* symptoms,const size_t len,const bool any_symptom)
    {
        const bool ERROR_START_PATH_NOT_EXISTS = !os::IsDir(dir);
        assert(!ERROR_START_PATH_NOT_EXISTS);
        if(ERROR_START_PATH_NOT_EXISTS)
            throw ::std::logic_error("ERROR_START_PATH_NOT_EXISTS");

        const os::path root = os::Root(dir);
        os::path p = dir; p.normalize();
        for(;;)
        {
            size_t n = 0;
            for(; n< len; ++n)
            {
                if(symptoms[n].empty())
                    continue;
                if(!os::Exists(p/symptoms[n]))
                    break;
                if(any_symptom)
                    return p;
            }
            if(n == len)
                return p;
            if(p==root)
                return "";
            p = p.parent_path();
        }
    }
    path FindPrev(const os::path& dir,const path& symptom)
    {
        if(symptom.empty())
            return "";

        const bool ERROR_START_PATH_NOT_EXISTS = !os::IsDir(dir);
        assert(!ERROR_START_PATH_NOT_EXISTS);
        if(ERROR_START_PATH_NOT_EXISTS)
            throw ::std::logic_error("ERROR_START_PATH_NOT_EXISTS");

        const os::path root = os::Root(dir);
        os::path p = dir; p.normalize();
        for(;;)
        if(os::Exists(p/symptom))
            return p;
        else if(p==root)
            return "";
        else
            p = p.parent_path();
    }
    //-----------------------------------------------------
    path FindNext(const path& dir,const path* symptoms,const size_t len,const bool any_symptom)
    {
        const bool ERROR_START_PATH_NOT_EXISTS = !os::IsDir(dir);
        assert(!ERROR_START_PATH_NOT_EXISTS);
        if(ERROR_START_PATH_NOT_EXISTS)
            throw ::std::logic_error("ERROR_START_PATH_NOT_EXISTS");

        typedef fs::recursive_directory_iterator It;
        for(It it(dir); it != It(); ++it)
        {
            bool failed = false;
            for(size_t n = 0; n< len; ++n)
            if(symptoms[n].empty())
                continue;
            else if(!os::Exists(*it/symptoms[n]))
                failed = true;
            else if(any_symptom)
                return *it;
            if(!failed)
                return *it;
        }
        return "";
    }
    path FindNext(const os::path& dir,const path& symptom)
    {
        if(symptom.empty())
            return "";

        const bool ERROR_START_PATH_NOT_EXISTS = !os::IsDir(dir);
        assert(!ERROR_START_PATH_NOT_EXISTS);
        if(ERROR_START_PATH_NOT_EXISTS)
            throw ::std::logic_error("ERROR_START_PATH_NOT_EXISTS");

        typedef fs::recursive_directory_iterator It;
        for(It it(dir); it != It(); ++it)
            if(os::Exists(*it/symptom))
                return *it;
        return "";
    }

}//namespace os

